#pragma once
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<memory>
#include<pthread.h>
#include<unistd.h>
#include<functional>

namespace wbj
{
#define THREAD_NUM 10
template<class T>
class ThreadPool
{
    using func_t=std::function<void(T&)>;
public:
    ThreadPool(func_t func,int num=THREAD_NUM)
    :_num(num),_threads(num),_func(func)
    {
        _threads.resize(10);
        pthread_mutex_init(&_mtx,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_cond);
    }
    void Init()
    {

    }

    void Start()
    {
        //启动线程
            for(int i=0;i<_num;i++)
            {
                pthread_create(&_threads[i],nullptr,ThreadRoutine,this);
            }
    }
    func_t callBack(T &task)
    {
        _func(task);
    }
    static void* ThreadRoutine(void* args)
    {
        pthread_detach(pthread_self());

        auto ptr=static_cast<ThreadPool<T>*>(args);
        while(true)
        {
            //访问临界区，对任务队列加锁
            ptr->lockQueue();

            //访问临界区，任务队列空则等待，不空则去除数据
            while(ptr->isEmpty())
                ptr->threadWait();

            T task=ptr->PopTask();
            ptr->unlockQueue();
           
           task();
           ptr->callBack(task);
           //std::cout<<task.getResult()<<std::endl;
        }
    }
    //放入数据后唤醒线程，回调函数：不断判断队列是否为空，空则等待
    void PushTask(const T& task)
    {
        lockQueue();
        
        _tasks.push(task);
        
        threadWakeup();
        unlockQueue(); 
    }
    T PopTask()
    {
        T task=_tasks.front();
        _tasks.pop();
        return task;
    }


    void lockQueue()
    {
        pthread_mutex_lock(&_mtx);
    }
    void unlockQueue()
    {
        pthread_mutex_unlock(&_mtx);
    }
    void threadWait()
    {
        pthread_cond_wait(&_cond,&_mtx);
    }
    void threadWakeup()
    {
        pthread_cond_signal(&_cond);
    }
    bool isEmpty()
    {
        return _tasks.empty();
    }
private:
    std::vector<pthread_t> _threads;
    int _num;//最大线程数量
    std::queue<T> _tasks;
    pthread_mutex_t _mtx;
    pthread_cond_t _cond;
    func_t _func;
};
}